package main

import (
	"fmt"
	"os"
	"time"
)

type FileLog struct {
	logPath string
	logName string
	file *os.File
	logDataChan chan *LogData
	logSplitType string
	logSplitSize int64
	lastSplitHour int
}

func NewFileLog() (log *FileLog,err error){
	//路径解析

	var logPath string
	if logPath = log_config.GetFilePath(); logPath == ""{
		err = fmt.Errorf("not fount log path")
		return
	}

	//名字解析
	var logName string
	if logName = log_config.GetFileName(); logName == "" {
		err = fmt.Errorf("not fount log name")
		return
	}

	//chan大小解析
	chanSize := log_config.GetChannelSize()

	//分割类型
	logSplitType := log_config.GetSplitType()

	//分割大小
	logSplitSize := log_config.GetSplitSize()

	log = &FileLog{
		logPath:      logPath,
		logName:      logName,
		logDataChan:  make(chan *LogData, chanSize),
		logSplitType: logSplitType,
		logSplitSize: logSplitSize,
		lastSplitHour: time.Now().Hour(),
	}
	log.init()
	return log,err
}


func (this *FileLog) writeLog() {
	for logData := range this.logDataChan {
		this.toSplitFile()
		fmt.Fprintf(this.file, "%s %s [%s/%s:%d] %s\n", logData.TimeStr, logData.LevelStr,logData.FileName, logData.FuncName, logData.LineNo, logData.Message)
	}
}

// 判断split类型，并且split
func (this *FileLog) toSplitFile(){
	switch  this.logSplitType{
	case LogSplitTypeHour:
		this.HourSplit()
	case LogSplitTypeSize:
		this.SizeSplit()
	default:
		this.HourSplit()
	}
}

func (this *FileLog)SizeSplit(){
	fileInfo , err := this.file.Stat()
	if err != nil {
		return
	}
	fileSize := fileInfo.Size()

	//大小判断
	if fileSize <= this.logSplitSize {
		return
	}
	now := time.Now()

	backupFileNmae := fmt.Sprintf("%s/%s.log_%s", this.logPath, this.logName, now.Format("20060102150405"))
	fileName := fmt.Sprintf("%s/%s", this.logPath, this.logName)
	this.file.Close()
	os.Rename(fileName, backupFileNmae)

	file, err := os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
	if err != nil{
		return
	}
	this.file = file
}

func (this *FileLog)HourSplit(){
	now := time.Now() //毫秒
	hour := now.Hour() //小时

	//时间判断
	if hour == this.lastSplitHour {
		return
	}
	this.lastSplitHour = hour

	//以前的log改名
	backupFileNmae := fmt.Sprintf("%s/%s.log_%s", this.logPath, this.logName, now.Format("20060102150405"))
	fileName := fmt.Sprintf("%s/%s", this.logPath, this.logName)
	this.file.Close()
	os.Rename(fileName, backupFileNmae)

	//创建新的
	file, err := os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
	if err != nil{
		return
	}
	this.file = file
}

func (this *FileLog) init(){
	fileName := fmt.Sprintf("%s/%s.log",this.logPath, this.logName)
	file, err := os.OpenFile(fileName,os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
	if err != nil {
		panic(fmt.Sprintf("Open File %s fail ,err : %v",fileName, err))
	}
	this.file = file
	go this.writeLog()
}

func (this *FileLog) Info(format string, args ...interface{}) {
	logData := MsgInfo(INFO,format,args)
	select {
	case this.logDataChan <- logData:
	default:
	}
}
func (this *FileLog) Debug(format string, args ...interface{}) {
	logData := MsgInfo(DEBUG,format,args)
	select {
	case this.logDataChan <- logData:
	default:
	}
}
func (this *FileLog) Error(format string, args ...interface{}){
	logData := MsgInfo(ERROR,format,args)
	select {
	case this.logDataChan <- logData:
	default:
	}
}
func (this *FileLog) Warn(format string, args ...interface{}){
	logData := MsgInfo(WARN,format,args)
	select {
	case this.logDataChan <- logData:
	default:
	}
}
func (this *FileLog) Close(){
	this.file.Close()
}